VPC エンドポイントタイプの Transfer for SFTP を Terraform で作ってみた
先日、CloudFormation で Transfer for SFTP を作成できるようになりましたが、今回は Terraform で作成してみました。
ちなみに Terraform AWS プロバイダの CHANGELOG を参照すると、2018年12月13日リリースの 1.52.0
で aws_transfer_server
が追加されていました。Transfer for SFTP がリリースされたのは2018年11月26日ですので、3週間弱で使えるようになってたってことですね。早いですねー。すごいですねー。
という Terraform 好きの白々しいポジトークをしつつ、さっそく試していきます。
今回の環境
今回はパブリックエンドポイントではなく、VPC エンドポイントの Transfer for SFTP を作成します。検証した際の、バージョンは下記のとおりです。(まだ v0.12 あげてません。。)
$ terraform -v Terraform v0.11.11 + provider.aws v2.12.0
今回は VPC エンドポイントタイプになりますので、provider.aws v2.6.0 以上が必要となります。
tf ファイル
作成した tf ファイルは以下のとおりです。VPC やサブネット、S3 など割愛してている Terraform リソースは xxxx
にしていますので、ご自身の環境に読み替えてください。
security-group.tf
VPC エンドポイントに割り当てるセキュリティグループを作成します。今回は VPC の CIDR 内から 22 番を許可しました。
resource "aws_security_group" "sftp-vpce-sg" { name = "sftp-vpce-sg" description = "Security Group for SFTP VPC Endpoint" vpc_id = "${aws_vpc.xxxx.id}" # VPC 内からの接続を許可 ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = [ "${aws_vpc.xxxx.cidr_block}", ] } }
VPC エンドポイントの作成
Transfer for SFTP と VPC をつなぐ VPC エンドポイントを作成します。service_name
は com.amazonaws.ap-northeast-1.transfer.server
を指定します。
#-------------------------------------- # VPC Endpoint #-------------------------------------- resource "aws_vpc_endpoint" "sftp-vpce" { vpc_id = "${aws_vpc.xxxx.id}" service_name = "com.amazonaws.ap-northeast-1.transfer.server" vpc_endpoint_type = "Interface" # 先ほど作成した VPC エンドポイント用の SG を指定 security_group_ids = [ "${aws_security_group.sftp-vpce-sg.id}", ] # VPC エンドポイントを作成するサブネットを指定 subnet_ids = [ "${aws_subnet.xxxx.id}", "${aws_subnet.xxxx.id}", ] private_dns_enabled = true }
IAM ロールおよびポリシーの作成
作成するロールは以下の2つです。
- ログ出力用
- SFTP ユーザ 用
まずはポリシードキュメントを用意しておきます。
#-------------------------------------- # IAM Policy Document #-------------------------------------- # Transfer for SFTP の assume policy data "aws_iam_policy_document" "assume-sftp" { statement { sid = "AssumeTransferforSFTP" actions = [ "sts:AssumeRole", ] principals { type = "Service" identifiers = [ "transfer.amazonaws.com", ] } } } # ログ出力用のポリシー data "aws_iam_policy_document" "cwl-full" { statement { sid = "AllowFullAccesstoCloudWatchLogs" actions = [ "logs:*", ] resources = [ "*", ] } } # SFTP ユーザ用のポリシー data "aws_iam_policy_document" "sftpuser" { statement { sid = "AllowBucket" effect = "Allow" actions = [ "s3:GetBucketLocation", "s3:ListBucket", ] # ホームディレクトリの S3 バケット resources = [ "${aws_s3_bucket.xxxx.arn}", ] } statement { sid = "AllowObject" effect = "Allow" actions = [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:DeleteObjectVersion", "s3:GetObjectVersion", ] # ホームディレクトリの S3 バケット resources = [ "${aws_s3_bucket.xxxx.arn}/*", ] } }
先ほどのポリシードキュメントを使って、IAM ポリシーを定義します。SFTP ユーザ用のポリシーは、今回はインラインポリシーにしたいので、ここではポリシー定義していません。(利用頻度が高いのであれば、定義すると良いかと思います)
#-------------------------------------- # IAM Policy #-------------------------------------- resource "aws_iam_policy" "cwl-full" { name = "cloudwatch-logs-full-policy" policy = "${data.aws_iam_policy_document.cwl-full.json}" }
そして IAM ロールを作成およびポリシーをアタッチします。
#-------------------------------------- # IAM Role #-------------------------------------- # ログ出力用 IAM ロール resource "aws_iam_role" "sftp-log-role" { name = "sftp-log-role" assume_role_policy = "${data.aws_iam_policy_document.assume-sftp.json}" } # SFTP ユーザ用 IAM ロール resource "aws_iam_role" "sftpuser-role" { name = "sftpuser-role" assume_role_policy = "${data.aws_iam_policy_document.assume-sftp.json}" } #-------------------------------------- # IAM Policy Attachment #-------------------------------------- # ログ出力用 IAM ロールにポリシーをアタッチ resource "aws_iam_policy_attachment" "sftp-log-role" { name = "sftp-log-role" roles = [ "${aws_iam_role.sftp-log-role.id}", ] policy_arn = "${aws_iam_policy.cwl-full.arn}" } #-------------------------------------- # IAM Role Policy #-------------------------------------- # SFTP ユーザ用 インラインポリシーをアタッチ resource "aws_iam_role_policy" "sftpuser-role" { name = "sftpuser-role-policy" role = "${aws_iam_role.sftpuser-role.id}" policy = "${data.aws_iam_policy_document.sftpuser.json}" }
そして Transfer for SFTP
前置きがながくなりましたが、ようやく Transfer for SFTP のリソース定義です。
#-------------------------------------- # Transfer Server #-------------------------------------- resource "aws_transfer_server" "sftp-server" { identity_provider_type = "SERVICE_MANAGED" # ログ出力用の IAM ロール logging_role = "${aws_iam_role.sftp-log-role.arn}" endpoint_details { vpc_endpoint_id = "${aws_vpc_endpoint.sftp-vpce.id}" } # VPC エンドポイントタイプを指定 endpoint_type = "VPC_ENDPOINT" } #-------------------------------------- # Transfer user #-------------------------------------- resource "aws_transfer_user" "sftp-user" { server_id = "${aws_transfer_server.sftp-server.id}" user_name = "sftpuser" # ホームディレクトリに使用する S3 バケット名を指定 home_directory = "/${aws_s3_bucket.xxxx.id}" # SFTP ユーザ用の IAM ロールを指定 role = "${aws_iam_role.sftpuser-role.arn}" } #-------------------------------------- # Transfer ssh key #-------------------------------------- resource "aws_transfer_ssh_key" "sftp-ssh-key" { server_id = "${aws_transfer_server.sftp-server.id}" user_name = "${aws_transfer_user.sftp-ssnb.user_name}" # SSH 公開鍵を指定 body = "ssh-rsa AAAABBBBBBCCCCCCC・・・・・" }
接続に使用する SSH 公開鍵 を body
に指定します。以下のコマンドでキーペアファイルを利用することも可能です。
$ chmod 400 key-pair.pem $ ssh-keygen -y -f key-pair.pem ssh-rsa AAAABBBBBBCCCCCCC・・・・(省略)
tf ファイルが作成できましたら、terraform plan
して terraform apply
で構築しましょう!
接続してみる
今回、VPC エンドポイントタイプとして作成しましたので、sftp クライアントからの接続先は VPC エンドポイントの FQDN になります。先ほどの SSH キーの秘密鍵を使って接続します。
$ sftp -i key-pair.pem sftpuser@vpce-05xxxxxxxxx-xxxxxxxx.server.transfer.ap-northeast-1.vpce.amazonaws.com sftp>
ログインできたので put
や get
が正しくできるか確認します。
# PUT sftp> put test.txt Uploading test.txt to /<home_directory>/test.txt text.txt 100% 5 0.7KB/s 00:00 # GET sftp> get test.txt Fetching /<home_directory>/test.txt to test.txt /<home_directory>/test.txt 100% 5 0.1KB/s 00:00
問題なく SFTP できることが確認できました!
さいごに
今回は1ユーザでの利用想定でしたが、次は複数ユーザを想定したスコープダウンポリシーも Terraform で作成してみたいと思います。
以上!大阪オフィスの丸毛(@marumo1981)でした!